package com.atguigu.filter;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.client.utils.IPUtil;
import com.atguigu.result.RetVal;
import com.atguigu.result.RetValCodeEnum;
import com.atguigu.util.IpUtil;
import org.apache.http.HttpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author ：Hachimen
 * @date ：Created in 2021/9/4 16:39
 * @description：网关请求拦截器
 * @modified By：
 * @version:
 */
@Component
public class AuthGlobalFilter implements GlobalFilter {
    // 创建匹配对象
    private AntPathMatcher antPathMatcher = new AntPathMatcher();
    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${filter.whiteList}")
    private String filterWhiteList;

    // 拦截过滤方法
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求request
        ServerHttpRequest request = exchange.getRequest();
        //获取请求当中的路径
        String path = request.getURI().getPath();
        //这个path中不能访问/sku/getSkuInfo/{skuId}中的数据信息
        if(antPathMatcher.match("/sku/**",path)){
            ServerHttpResponse response = exchange.getResponse();
            return writeDataToBrowser(response, RetValCodeEnum.NO_PERMISSION);
        }
        //获取用户的id信息
        String userId = getUserId(request);
        //获取用户临时id信息
        String userTempId = getUserTempId(request);
        if("-1".equals(userId)){
            //ip不匹配
            ServerHttpResponse response = exchange.getResponse();
            return writeDataToBrowser(response, RetValCodeEnum.NO_PERMISSION);
        }
        //如果要看订单相关信息是需要进行登录的
        if(antPathMatcher.match("/order/**",path)){
            if(StringUtils.isEmpty(userId)){
                ServerHttpResponse response = exchange.getResponse();
                return writeDataToBrowser(response, RetValCodeEnum.NO_LOGIN);
            }
        }

        //访问拦截路径名单 对于这些请求路径需要进行拦截
        for (String filterWhite : filterWhiteList.split(",")) {
               if(path.indexOf(filterWhite)!=-1&&StringUtils.isEmpty(userId)){
                   ServerHttpResponse response = exchange.getResponse();
                   response.setStatusCode(HttpStatus.SEE_OTHER);
                   response.getHeaders().set(HttpHeaders.LOCATION,"http://passport.gmall.com/login.html?originalUrl="+request.getURI());
                   return response.setComplete();
               }
        }
        //如果说用户登录了呢，那么我们就需要将userId放到request中
        if(!StringUtils.isEmpty(userId)){
            request.mutate().header("userId",userId).build();
            return chain.filter(exchange.mutate().request(request).build());
        }
        if(!StringUtils.isEmpty(userTempId)){
            request.mutate().header("userTempId",userTempId).build();
            return chain.filter(exchange.mutate().request(request).build());
        }



        return chain.filter(exchange);
    }

    private String getUserTempId(ServerHttpRequest request) {
        String userTempId = "";
        List<String> userTempIdList = request.getHeaders().get("userTempId");
        if (!CollectionUtils.isEmpty(userTempIdList)){
            userTempId = userTempIdList.get(0);
        }else{
            HttpCookie cookie = request.getCookies().getFirst("userTempId");
            if (cookie != null){
                userTempId = cookie.getValue();
            }
        }
        return userTempId;
    }

    private String getUserId(ServerHttpRequest request) {
        String token = "";
        List<String> tokenList = request.getHeaders().get("token");
        if (!CollectionUtils.isEmpty(tokenList)){
            token = tokenList.get(0);
        }else{
            HttpCookie cookie = request.getCookies().getFirst("token");
            if (cookie != null){
                token = cookie.getValue();
            }
        }
        if(!StringUtils.isEmpty(token)){
            String key = "user:login:"+token;
            String idJson = (String) redisTemplate.opsForValue().get(key);
            JSONObject loginInfo = JSONObject.parseObject(idJson);
            String loginIp = loginInfo.getString("loginIp");
            String gatwayIpAddress = IpUtil.getGatwayIpAddress(request);
            if(gatwayIpAddress.equals(loginIp)){
                return loginInfo.getString("userId");
            }else{
                return "-1";
            }

        }
        return null;
    }

    private Mono<Void> writeDataToBrowser(ServerHttpResponse response, RetValCodeEnum retValCodeEnum) {
        RetVal<Object> retVal = RetVal.build(null, retValCodeEnum);
        byte[] bytes = JSONObject.toJSONString(retVal).getBytes(StandardCharsets.UTF_8);
        DataBuffer dataBuffer = response.bufferFactory().wrap(bytes);
        response.getHeaders().add("Content-Type","application/json;charset=UTF-8");
        return response.writeWith(Mono.just(dataBuffer));
    }
}
